// Command-based authentication - execute external command for auth

use super::Authenticator;
use async_trait::async_trait;
use std::process::Command;
use tracing::{debug, warn};

pub struct CommandAuthenticator {
    command: String,
}

impl CommandAuthenticator {
    pub fn new(command: String) -> Self {
        Self { command }
    }
}

#[async_trait]
impl Authenticator for CommandAuthenticator {
    async fn authenticate(&self, auth: &str, addr: &str) -> bool {
        debug!("Command auth: executing command for {}", addr);
        
        // Execute command with auth and addr as arguments
        let output = Command::new("sh")
            .arg("-c")
            .arg(&self.command)
            .env("HYSTERIA_AUTH", auth)
            .env("HYSTERIA_ADDR", addr)
            .output();
        
        match output {
            Ok(output) => {
                let success = output.status.success();
                if !success {
                    warn!("Command auth failed for {}: {:?}", addr, output.stderr);
                }
                success
            }
            Err(e) => {
                warn!("Command auth error for {}: {}", addr, e);
                false
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_command_auth() {
        // Test with a simple echo command
        let auth = CommandAuthenticator::new("exit 0".to_string());
        assert!(auth.authenticate("test", "127.0.0.1").await);
        
        let auth = CommandAuthenticator::new("exit 1".to_string());
        assert!(!auth.authenticate("test", "127.0.0.1").await);
    }
}
